package com.wengu.algorithm.alg;

import com.wengu.algorithm.dto.TaskAlg;
import com.wengu.algorithm.dto.UserAlg;
import com.wengu.algorithm.entity.AssignmentOutcome;
import com.wengu.algorithm.service.AssignmentOutcomeUserService;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * ETDA算法实现
 */

@Slf4j
public class EDBA extends QEA {


    // 空间索引结构，用于快速查找附近任务
//    private SpatialIndex spatialIndex;
    // 当前处理的用户引用
    public UserAlg currentUser;



    /**
     * 构造函数，初始化算法参数
     * @param alpha 权重调节参数
     * @param gamma 参数
     */
    public EDBA(double alpha, double gamma,double mu) {
        // 参数校验
        validateParameters(gamma, alpha);
        this.gamma = gamma;
        this.alpha = alpha;
        this.mu = mu;
    }




    /**
     * 分配任务方法
     *
     * @param user                         当前用户
     * @param allTasks                     所有待分配任务列表
     * @param assignmentOutcome            分配结果
     * @param assignmentOutcomeUserService 用户服务
     * @param taskCacheMap                 任务缓存映射
     * @param algName                      算法名称
     * @param notIncreaseTaskIdSet
     * @return 分配的任务列表
     */
    @Override
    public List<TaskAlg> allocateTasks(UserAlg user, List<TaskAlg> allTasks, AssignmentOutcome assignmentOutcome,
                                       AssignmentOutcomeUserService assignmentOutcomeUserService,
                                       Map<Long, TaskAlg> taskCacheMap, String algName, Set<Long> notIncreaseTaskIdSet) {
        this.currentUser = user;  // 更新当前用户
        return super.allocateTasks(user, allTasks, assignmentOutcome, assignmentOutcomeUserService, taskCacheMap, algName, notIncreaseTaskIdSet);
    }

    /**
     * 异步多线程执行
     * 分配任务方法
     *
     * @param user                         当前用户
     * @param allTasks                     所有待分配任务列表
     * @param assignmentOutcome            分配结果
     * @param assignmentOutcomeUserService 用户服务
     * @param taskCacheMap                 任务缓存映射
     * @param algName                      算法名称
     * @param notIncreaseTaskIdSet
     * @return 分配的任务列表
     */
    @Override
    public List<TaskAlg> allocateTasksAsync(UserAlg user, List<TaskAlg> allTasks, AssignmentOutcome assignmentOutcome,
                                       AssignmentOutcomeUserService assignmentOutcomeUserService,
                                       Map<Long, TaskAlg> taskCacheMap, String algName, Set<Long> notIncreaseTaskIdSet) {
        this.currentUser = user;  // 更新当前用户
        return super.allocateTasksAsync(user, allTasks, assignmentOutcome, assignmentOutcomeUserService, taskCacheMap, algName, notIncreaseTaskIdSet);
    }

    /**
     * 计算候选任务的效用值
     *
     * @param candidate            候选任务
     * @param allTasks             所有任务列表
     * @param weightCost           总成本
     * @param selectedTaskIdSet
     * @param notIncreaseTaskIdSet
     * @param deltaF
     * @param budget
     * @param usedCost
     * @return 效用值
     */
    @Override
    public double calculateUtility(TaskAlg candidate, List<TaskAlg> allTasks, double weightCost, Set<Long> selectedTaskIdSet, Set<Long> notIncreaseTaskIdSet, double deltaF, double budget, double usedCost) {

        double remainingBudget = budget - usedCost - calculateDistance(candidate.taskX, candidate.taskY, currentUser.destX, currentUser.destY) - candidate.executionCost;
        double aWeight = Math.pow(remainingBudget, mu);
        double bWeight = Math.pow(weightCost, gamma);
        return deltaF * aWeight / bWeight;  // 返回归一化的效用值
    }




    /**
     * 参数校验
     * @param gamma 参数
     * @param alpha alpha参数
     * @throws IllegalArgumentException 如果参数不合法
     */
    private void validateParameters(double gamma, double alpha) {
        if (gamma < 0) {
            throw new IllegalArgumentException("Gamma must be positive");
        }
        if (alpha < 0) {
            throw new IllegalArgumentException("Alpha must be larger than 0");
        }
    }

}